/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "zobjects_json.h"

#define OBJ_STACK_TALL		64

#define OBJECTTOSTRING_STYLE_COMPACT	0
#define OBJECTTOSTRING_STYLE_INDENT_TAB	1

struct ZlangDirectProperty_json
{
	int		dummy ;
} ;

struct CallbackOnJsonNodeUserData
{
	char			*json_str ;
	struct ZlangRuntime	*rt ;
	struct ZlangObject	*obj_stack[ OBJ_STACK_TALL ] ;
	struct ZlangObject	**obj_stack_top ;
	unsigned char		is_enti_obj ;
} ;

funcCallbackOnJsonNode CallbackOnJsonNode;
int CallbackOnJsonNode( int type , char *jpath , int jpath_len , int jpath_size , char *node , int node_len , char *content , int content_len , void *p )
{
	struct CallbackOnJsonNodeUserData	*user_data = (struct CallbackOnJsonNodeUserData *)p ;
	
	char					obj_name[ 256 ] = "" ;
	struct ZlangObject			*name_obj = NULL ;
	struct ZlangObject			*child_obj = NULL ;
	struct ZlangObject			*append_obj = NULL ;
	char					*ext_obj_name = NULL ;
	struct ZlangObject			*clone_obj = NULL ;
	
	int					nret = 0 ;
	
	TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "obj_stack_top depth[%d] - type[0x%x] jpath[%.*s] node[%.*s] content[%.*s] - rt[%p] obj_stack[%p] obj_stack_top[%p]" , (int)(user_data->obj_stack_top-user_data->obj_stack) , type , jpath_len,jpath , node_len,node , content_len,content , user_data->rt , user_data->obj_stack , user_data->obj_stack_top )
	
	if( jpath_len == 0 )
		return 0;
	
	if( type == FASTERJSON_NODE_LEAF )
	{
		if( content > user_data->json_str && content[-1] == '"' )
		{
			snprintf( obj_name , sizeof(obj_name)-1 , "%.*s" , node_len,node );
			if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
			{
				child_obj = CloneStringObject( user_data->rt , obj_name ) ;
				if( child_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneStringObject failed" )
					return -111;
				}
				
				nret = CallRuntimeFunction_string_SetStringValue( user_data->rt , child_obj , content , content_len ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
					DestroyObject( user_data->rt , child_obj );
					return -112;
				}
				
				if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_array_Append( user_data->rt , *(user_data->obj_stack_top) , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append failed" )
						DestroyObject( user_data->rt , child_obj );
						return -113;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_list_AddTail( user_data->rt , *(user_data->obj_stack_top) , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail failed" )
						DestroyObject( user_data->rt , child_obj );
						return -113;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					name_obj = CloneStringObject( user_data->rt , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneStringObject failed" )
						DestroyObject( user_data->rt , child_obj );
						return -111;
					}
					
					nret = CallRuntimeFunction_string_SetStringValue( user_data->rt , name_obj , node , node_len ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -112;
					}
					
					nret = CallRuntimeFunction_map_Put( user_data->rt , *(user_data->obj_stack_top) , name_obj , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put failed" )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -113;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put[%p][%s][%s][%.*s]-[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , name_obj , GetCloneObjectName(name_obj) , GetObjectName(name_obj) , node_len,node , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
					
					DestroyObject( user_data->rt , name_obj );
				}
				
				DestroyObject( user_data->rt , child_obj );
			}
			else
			{
				if( user_data->is_enti_obj == 0 )
				{
					child_obj = AddPropertyInObject( user_data->rt , *(user_data->obj_stack_top) , GetStringObjectInRuntimeObjectsHeap(user_data->rt) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddPropertyInObject failed" )
						return -121;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddStringPropertyInObject[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else
				{
					child_obj = QueryPropertyInObjectByPropertyName( user_data->rt , *(user_data->obj_stack_top) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] not found in obj[%s]" , obj_name , GetObjectName(*(user_data->obj_stack_top)) )
						return -121;
					}
					
					if( IsTypeOf( user_data->rt , child_obj , GetStringObjectInRuntimeObjectsHeap(user_data->rt) ) == 0 )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] type not matched" , obj_name )
						return 0;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "SetStringPropertyInObject[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				
				nret = CallRuntimeFunction_string_SetStringValue( user_data->rt , child_obj , content , content_len ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
					return -122;
				}
			}
		}
		else if( memchr( content , '.' , content_len ) )
		{
			char		buf[ 100 ] = "" ;
			
			snprintf( obj_name , sizeof(obj_name)-1 , "%.*s" , node_len,node );
			if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
			{
				child_obj = CloneDoubleObject( user_data->rt , obj_name ) ;
				if( child_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneDoubleObject failed" )
					return -211;
				}
				
				snprintf( buf , sizeof(buf)-1 , "%.*s" , content_len,content );
				nret = CallRuntimeFunction_double_SetDoubleValue( user_data->rt , child_obj , atof(buf) ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_double_SetDoubleValue failed[%d]" , nret )
					DestroyObject( user_data->rt , child_obj );
					return -212;
				}
				
				if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_array_Append( user_data->rt , *(user_data->obj_stack_top) , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append failed" )
						DestroyObject( user_data->rt , child_obj );
						return -213;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_list_AddTail( user_data->rt , *(user_data->obj_stack_top) , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail failed" )
						DestroyObject( user_data->rt , child_obj );
						return -213;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					name_obj = CloneStringObject( user_data->rt , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneStringObject failed" )
						DestroyObject( user_data->rt , child_obj );
						return -111;
					}
					
					nret = CallRuntimeFunction_string_SetStringValue( user_data->rt , name_obj , node , node_len ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -112;
					}
					
					nret = CallRuntimeFunction_map_Put( user_data->rt , *(user_data->obj_stack_top) , name_obj , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put failed" )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -213;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put[%p][%s][%s][%.*s]-[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , name_obj , GetCloneObjectName(name_obj) , GetObjectName(name_obj) , node_len,node , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
					
					DestroyObject( user_data->rt , name_obj );
				}
				
				DestroyObject( user_data->rt , child_obj );
			}
			else
			{
				if( user_data->is_enti_obj == 0 )
				{
					child_obj = AddPropertyInObject( user_data->rt , *(user_data->obj_stack_top) , GetDoubleObjectInRuntimeObjectsHeap(user_data->rt) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddPropertyInObject failed" )
						return -221;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddDoublePropertyInObject[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else
				{
					child_obj = QueryPropertyInObjectByPropertyName( user_data->rt , *(user_data->obj_stack_top) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] not found in obj[%s]" , obj_name , GetObjectName(*(user_data->obj_stack_top)) )
						return -221;
					}
					
					if( IsTypeOf( user_data->rt , child_obj , GetDoubleObjectInRuntimeObjectsHeap(user_data->rt) ) == 0 )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] type not matched" , obj_name )
						return 0;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "SetDoublePropertyInObject[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				
				snprintf( buf , sizeof(buf)-1 , "%.*s" , content_len,content );
				nret = CallRuntimeFunction_double_SetDoubleValue( user_data->rt , child_obj , atof(buf) ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_double_SetDoubleValue failed[%d]" , nret )
					return -222;
				}
			}
		}
		else if( content[0] == 't' || content[0] == 'f' )
		{
			snprintf( obj_name , sizeof(obj_name)-1 , "%.*s" , node_len,node );
			if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
			{
				child_obj = CloneBoolObject( user_data->rt , obj_name ) ;
				if( child_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneBoolObject failed" )
					return -311;
				}
				
				if( content[0] == 't' )
					nret = CallRuntimeFunction_bool_SetBoolValue( user_data->rt , child_obj , TRUE ) ;
				else if( content[0] == 'f' )
					nret = CallRuntimeFunction_bool_SetBoolValue( user_data->rt , child_obj , FALSE ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_bool_SetBoolValue failed[%d]" , nret )
					DestroyObject( user_data->rt , child_obj );
					return -312;
				}
				
				if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_array_Append( user_data->rt , *(user_data->obj_stack_top) , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append failed" )
						DestroyObject( user_data->rt , child_obj );
						return -313;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_list_AddTail( user_data->rt , *(user_data->obj_stack_top) , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail failed" )
						DestroyObject( user_data->rt , child_obj );
						return -313;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					name_obj = CloneStringObject( user_data->rt , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneStringObject failed" )
						DestroyObject( user_data->rt , child_obj );
						return -111;
					}
					
					nret = CallRuntimeFunction_string_SetStringValue( user_data->rt , name_obj , node , node_len ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -112;
					}
					
					nret = CallRuntimeFunction_map_Put( user_data->rt , *(user_data->obj_stack_top) , name_obj , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put failed" )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -313;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put[%p][%s][%s][%.*s]-[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , name_obj , GetCloneObjectName(name_obj) , GetObjectName(name_obj) , node_len,node , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
					
					DestroyObject( user_data->rt , name_obj );
				}
				
				DestroyObject( user_data->rt , child_obj );
			}
			else
			{
				if( user_data->is_enti_obj == 0 )
				{
					child_obj = AddPropertyInObject( user_data->rt , *(user_data->obj_stack_top) , GetBoolObjectInRuntimeObjectsHeap(user_data->rt) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddBoolPropertyInObject failed" )
						return -321;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddDoublePropertyInObject[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else
				{
					child_obj = QueryPropertyInObjectByPropertyName( user_data->rt , *(user_data->obj_stack_top) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] not found in obj[%s]" , obj_name , GetObjectName(*(user_data->obj_stack_top)) )
						return -322;
					}
					
					if( IsTypeOf( user_data->rt , child_obj , GetBoolObjectInRuntimeObjectsHeap(user_data->rt) ) == 0 )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] type not matched" , obj_name )
						return 0;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "SetDoublePropertyInObject[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				
				if( content[0] == 't' )
					nret = CallRuntimeFunction_bool_SetBoolValue( user_data->rt , child_obj , TRUE ) ;
				else if( content[0] == 'f' )
					nret = CallRuntimeFunction_bool_SetBoolValue( user_data->rt , child_obj , FALSE ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_bool_SetBoolValue failed[%d]" , nret )
					return -322;
				}
			}
		}
		else if( content[0] == FASTERJSON_NULL[0] )
		{
			snprintf( obj_name , sizeof(obj_name)-1 , "%.*s" , node_len,node );
			if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
			{
				child_obj = CloneNullObject( user_data->rt , obj_name ) ;
				if( child_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneNullObject failed" )
					return -511;
				}
				
				if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_array_Append( user_data->rt , *(user_data->obj_stack_top) , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append failed" )
						DestroyObject( user_data->rt , child_obj );
						return -513;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_list_AddTail( user_data->rt , *(user_data->obj_stack_top) , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail failed" )
						DestroyObject( user_data->rt , child_obj );
						return -513;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					name_obj = CloneStringObject( user_data->rt , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneStringObject failed" )
						DestroyObject( user_data->rt , child_obj );
						return -111;
					}
					
					nret = CallRuntimeFunction_string_SetStringValue( user_data->rt , name_obj , node , node_len ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -112;
					}
					
					nret = CallRuntimeFunction_map_Put( user_data->rt , *(user_data->obj_stack_top) , name_obj , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put failed" )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -513;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put[%p][%s][%s][%.*s]-[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , name_obj , GetCloneObjectName(name_obj) , GetObjectName(name_obj) , node_len,node , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
					
					DestroyObject( user_data->rt , name_obj );
				}
				
				DestroyObject( user_data->rt , child_obj );
			}
			else
			{
				if( user_data->is_enti_obj == 0 )
				{
					child_obj = AddNullPropertyInObject( user_data->rt , *(user_data->obj_stack_top) , NULL , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddNullPropertyInObject failed" )
						return -521;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddNullPropertyInObject[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else
				{
					child_obj = QueryPropertyInObjectByPropertyName( user_data->rt , *(user_data->obj_stack_top) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] not found in obj[%s]" , obj_name , GetObjectName(*(user_data->obj_stack_top)) )
						return -522;
					}
					
					UnreferObject( user_data->rt , child_obj );
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "SetNullPropertyInObject[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
			}
		}
		else
		{
			char		buf[ 40 ] = "" ;
			
			snprintf( obj_name , sizeof(obj_name)-1 , "%.*s" , node_len,node );
			if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
			{
				child_obj = CloneIntObject( user_data->rt , obj_name ) ;
				if( child_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneIntObject failed" )
					return -611;
				}
				
				snprintf( buf , sizeof(buf)-1 , "%.*s" , content_len,content );
				nret = CallRuntimeFunction_int_SetIntValue( user_data->rt , child_obj , atoi(buf) ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
					DestroyObject( user_data->rt , child_obj );
					return -612;
				}
				
				if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_array_Append( user_data->rt , *(user_data->obj_stack_top) , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append failed" )
						DestroyObject( user_data->rt , child_obj );
						return -613;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_list_AddTail( user_data->rt , *(user_data->obj_stack_top) , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail failed" )
						DestroyObject( user_data->rt , child_obj );
						return -613;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					name_obj = CloneStringObject( user_data->rt , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneStringObject failed" )
						DestroyObject( user_data->rt , child_obj );
						return -111;
					}
					
					nret = CallRuntimeFunction_string_SetStringValue( user_data->rt , name_obj , node , node_len ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -112;
					}
					
					nret = CallRuntimeFunction_map_Put( user_data->rt , *(user_data->obj_stack_top) , name_obj , child_obj , NULL ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put failed" )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -613;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put[%p][%s][%s][%.*s]-[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , name_obj , GetCloneObjectName(name_obj) , GetObjectName(name_obj) , node_len,node , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
					
					DestroyObject( user_data->rt , name_obj );
				}
				
				DestroyObject( user_data->rt , child_obj );
			}
			else
			{
				if( user_data->is_enti_obj == 0 )
				{
					child_obj = AddPropertyInObject( user_data->rt , *(user_data->obj_stack_top) , GetIntObjectInRuntimeObjectsHeap(user_data->rt) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddPropertyInObject failed" )
						return -621;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddIntPropertyInObject[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else
				{
					child_obj = QueryPropertyInObjectByPropertyName( user_data->rt , *(user_data->obj_stack_top) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] not found in obj[%s]" , obj_name , GetObjectName(*(user_data->obj_stack_top)) )
						return -622;
					}
					
					if( IsTypeOf( user_data->rt , child_obj , GetIntObjectInRuntimeObjectsHeap(user_data->rt) ) == 0 )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] type not matched" , obj_name )
						return 0;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "SetIntPropertyInObject[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				
				snprintf( buf , sizeof(buf)-1 , "%.*s" , content_len,content );
				nret = CallRuntimeFunction_int_SetIntValue( user_data->rt , child_obj , atoi(buf) ) ;
				if( nret )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_int_SetIntValue failed[%d]" , nret )
					return -622;
				}
			}
		}
	}
	else if( type & FASTERJSON_NODE_ENTER )
	{
		if( type & FASTERJSON_NODE_BRANCH )
		{
			if( (char*)(user_data->obj_stack_top+1) - (char*)(user_data->obj_stack) >= sizeof(struct ZlangObject *)*OBJ_STACK_TALL )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "obj stack top overflow" )
				return -211;
			}
			
			snprintf( obj_name , sizeof(obj_name)-1 , "%.*s" , node_len,node );
			if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) || IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
			{
				if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
					ext_obj_name = GetObjectEmbellishName2( *(user_data->obj_stack_top) ) ;
				else
					ext_obj_name = GetObjectEmbellishName( *(user_data->obj_stack_top) ) ;
				if( ext_obj_name )
				{
					clone_obj = QueryObjectByObjectName( user_data->rt , ext_obj_name , NULL ) ;
					if( clone_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "QueryObjectByObjectName[%s] failed" , ext_obj_name )
						return -812;
					}
					
					nret = CloneObject( user_data->rt , & child_obj , NULL , clone_obj ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneObject failed" )
						return -812;
					}
					else
					{
						TEST_RUNTIME_DEBUG( user_data->rt ) { PRINT_TABS(user_data->rt) printf( "clone obj[%s] " , ext_obj_name ); DebugPrintObject( user_data->rt , clone_obj ); PRINT_SOURCE_FILE_LINE PRINT_NEWLINE }
					}
				}
				else
				{
					child_obj = CloneZObject( user_data->rt , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneZObject failed" )
						return -811;
					}
					else
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneZObject ok" )
					}
				}
				
				if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_array_Append( user_data->rt , *(user_data->obj_stack_top) , child_obj , & append_obj ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append failed" )
						DestroyObject( user_data->rt , child_obj );
						return -812;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_array_Append[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , append_obj , GetCloneObjectName(append_obj) , GetObjectName(append_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					nret = CallRuntimeFunction_list_AddTail( user_data->rt , *(user_data->obj_stack_top) , child_obj , & append_obj ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail failed" )
						DestroyObject( user_data->rt , child_obj );
						return -812;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_list_AddTail[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , append_obj , GetCloneObjectName(append_obj) , GetObjectName(append_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else if( IsTypeOf( user_data->rt , *(user_data->obj_stack_top) , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) )
				{
					name_obj = CloneStringObject( user_data->rt , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CloneStringObject failed" )
						DestroyObject( user_data->rt , child_obj );
						return -111;
					}
					
					nret = CallRuntimeFunction_string_SetStringValue( user_data->rt , name_obj , node , node_len ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_string_SetStringValue failed[%d]" , nret )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -112;
					}
					
					nret = CallRuntimeFunction_map_Put( user_data->rt , *(user_data->obj_stack_top) , name_obj , child_obj , & append_obj ) ;
					if( nret )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put failed" )
						DestroyObject( user_data->rt , name_obj );
						DestroyObject( user_data->rt , child_obj );
						return -812;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "CallRuntimeFunction_map_Put[%p][%s][%s][%.*s]-[%p][%s][%s][%.*s] in obj[%p][%s][%s]" , name_obj , GetCloneObjectName(name_obj) , GetObjectName(name_obj) , node_len,node , append_obj , GetCloneObjectName(append_obj) , GetObjectName(append_obj) , content_len,content , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
					
					DestroyObject( user_data->rt , name_obj );
				}
				
				DestroyObject( user_data->rt , child_obj );
			}
			else
			{
				if( user_data->is_enti_obj == 0 )
				{
					child_obj = AddPropertyInObject( user_data->rt , *(user_data->obj_stack_top) , GetZObjectInRuntimeObjectsHeap(user_data->rt) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddPropertyInObject failed" )
						return -813;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddPropertyInObject[%p][%s][%s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				else
				{
					child_obj = QueryPropertyInObjectByPropertyName( user_data->rt , *(user_data->obj_stack_top) , obj_name ) ;
					if( child_obj == NULL )
					{
						TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] not found in obj[%s]" , obj_name , GetObjectName(*(user_data->obj_stack_top)) )
						return -814;
					}
					
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "SetPropertyInObject[%p][%s][%s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
				}
				
				append_obj = child_obj ;
			}
			
			TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "stack top is obj[%p][%s][%s]" , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
			user_data->obj_stack_top++;
			*(user_data->obj_stack_top) = append_obj ;
			TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "push branch obj[%p][%s][%s] to stack top" , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
			OffsetRuntimeRecursizeDepth( user_data->rt , 1 );
		}
		else if( type & FASTERJSON_NODE_ARRAY )
		{
			if( (char*)(user_data->obj_stack_top+1) - (char*)(user_data->obj_stack) >= sizeof(struct ZlangObject *)*OBJ_STACK_TALL )
			{
				TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "obj stack top overflow" )
				return -821;
			}
			
			snprintf( obj_name , sizeof(obj_name)-1 , "%.*s" , node_len,node );
			
			if( user_data->is_enti_obj == 0 )
			{
				child_obj = AddPropertyInObject( user_data->rt , *(user_data->obj_stack_top) , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) , obj_name ) ;
				if( child_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddPropertyInObject failed" )
					return -822;
				}
				
				TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "AddPropertyInObject[%p][%s][%s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
			}
			else
			{
				child_obj = QueryPropertyInObjectByPropertyName( user_data->rt , *(user_data->obj_stack_top) , obj_name ) ;
				if( child_obj == NULL )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] not found in obj[%s]" , obj_name , GetObjectName(*(user_data->obj_stack_top)) )
					return -823;
				}
				
				if( IsTypeOf( user_data->rt , child_obj , GetArrayObjectInRuntimeObjectsHeap(user_data->rt) ) == 0 && IsTypeOf( user_data->rt , child_obj , GetListObjectInRuntimeObjectsHeap(user_data->rt) ) == 0 && IsTypeOf( user_data->rt , child_obj , GetMapObjectInRuntimeObjectsHeap(user_data->rt) ) == 0 )
				{
					TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "property[%s] type not matched" , obj_name )
					return 0;
				}
				
				TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "SetPropertyInObject[%p][%s][%s] in obj[%p][%s][%s]" , child_obj , GetCloneObjectName(child_obj) , GetObjectName(child_obj) , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
			}
			
			TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "stack top is obj[%p][%s][%s]" , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
			user_data->obj_stack_top++;
			*(user_data->obj_stack_top) = child_obj ;
			TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "push array obj[%p][%s][%s] to stack top" , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
			OffsetRuntimeRecursizeDepth( user_data->rt , 1 );
		}
	}
	else if( type & FASTERJSON_NODE_LEAVE )
	{
		if( type & FASTERJSON_NODE_BRANCH )
		{
			OffsetRuntimeRecursizeDepth( user_data->rt , -1 );
			TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "popup branch obj[%p][%s][%s] from stack top" , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
			user_data->obj_stack_top--;
			TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "stack top is obj[%p][%s][%s] now" , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
		}
		else if( type & FASTERJSON_NODE_ARRAY )
		{
			OffsetRuntimeRecursizeDepth( user_data->rt , -1 );
			TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "popup array obj[%p][%s][%s] from stack top" , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
			user_data->obj_stack_top--;
			TEST_RUNTIME_DEBUG_THEN_PRINT( user_data->rt , "stack top is obj[%p][%s][%s] now" , *(user_data->obj_stack_top) , GetCloneObjectName(*(user_data->obj_stack_top)) , GetObjectName(*(user_data->obj_stack_top)) )
		}
	}
	
	return 0;
}

ZlangDirectFunction_json_StringToObject json_StringToObject;
int json_StringToObject( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *s , struct ZlangObject *o )
{
	char					*json_str = NULL ;
	int32_t					json_str_len ;
	char					jpath[ 4096 ] = "" ;
	struct CallbackOnJsonNodeUserData	user_data ;
	
	int					nret = 0 ;
	
	CallRuntimeFunction_string_GetStringValue( rt , s , & json_str , & json_str_len );
	
	memset( & user_data , 0x00 , sizeof(struct CallbackOnJsonNodeUserData) );
	user_data.json_str = json_str ;
	user_data.rt = rt ;
	user_data.obj_stack[0] = o ;
	user_data.obj_stack_top = user_data.obj_stack ;
	user_data.is_enti_obj = 0 ;
	nret = TravelJsonBuffer( json_str , jpath , sizeof(jpath) , CallbackOnJsonNode , & user_data ) ;
	if( nret )
	{
		return nret;
	}
	
	if( user_data.obj_stack_top != user_data.obj_stack )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_INTERNAL , "user_data.obj_stack_top depth[%d] after calling TravelJsonBuffer" , (int)(user_data.obj_stack_top-user_data.obj_stack) )
		return ZLANG_ERROR_INTERNAL;
	}
	
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_json_StringToObject_string;
int ZlangInvokeFunction_json_StringToObject_string( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangObject		*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int				nret = 0 ;
	
	nret = json_StringToObject( rt , obj , in1 , out1 ) ;
	if( nret )
	{
		nret = UnreferObject( rt , out1 ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InitObject failed[%d]" , nret )
			return nret;
		}
		
		return ThrowErrorException( rt , EXCEPTION_CODE_GENERAL , EXCEPTION_MESSAGE_STRING_TO_OBJECT_FAILED );
	}
	
	return 0;
}

ZlangDirectFunction_json_StringToObject json_StringToEntityObject;
int json_StringToEntityObject( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *s , struct ZlangObject *o )
{
	char					*json_str = NULL ;
	int32_t					json_str_len ;
	char					jpath[ 4096 ] = "" ;
	struct CallbackOnJsonNodeUserData	user_data ;
	
	int					nret = 0 ;
	
	CallRuntimeFunction_string_GetStringValue( rt , s , & json_str , & json_str_len );
	
	memset( & user_data , 0x00 , sizeof(struct CallbackOnJsonNodeUserData) );
	user_data.json_str = json_str ;
	user_data.rt = rt ;
	user_data.obj_stack[0] = o ;
	user_data.obj_stack_top = user_data.obj_stack ;
	user_data.is_enti_obj = 1 ;
	nret = TravelJsonBuffer( json_str , jpath , sizeof(jpath) , CallbackOnJsonNode , & user_data ) ;
	if( nret )
	{
		return nret;
	}
	
	if( user_data.obj_stack_top != user_data.obj_stack )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_INTERNAL , "user_data.obj_stack_top depth[%d] after calling TravelJsonBuffer" , (int)(user_data.obj_stack_top-user_data.obj_stack) )
		return ZLANG_ERROR_INTERNAL;
	}
	
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_json_StringToEntityObject_string_object;
int ZlangInvokeFunction_json_StringToEntityObject_string_object( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangObject		*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject		*in2 = GetInputParameterInLocalObjectStack(rt,2) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int				nret = 0 ;
	
	nret = json_StringToEntityObject( rt , obj , in1 , in2 ) ;
	if( nret )
	{
		CallRuntimeFunction_bool_SetBoolValue( rt , out1 , FALSE );
		return ThrowErrorException( rt , EXCEPTION_CODE_GENERAL , EXCEPTION_MESSAGE_STRING_TO_ENTITY_OBJECT_FAILED );
	}
	
	CallRuntimeFunction_bool_SetBoolValue( rt , out1 , TRUE );
	return 0;
}

static int ArrayObjectToString( struct ZlangRuntime *rt , struct ZlangObject *o , struct ZlangObject *s , int32_t obj_to_str_style , int32_t depth );

static int ObjectToString( struct ZlangRuntime *rt , struct ZlangObject *o , struct ZlangObject *s , int32_t obj_to_str_style , int32_t depth )
{
	struct ZlangObject	*prop = NULL ;
	char			*prop_name = NULL ;
	int32_t			prop_name_len ;
	char			**buf = NULL ;
	int32_t			*buf_len = NULL ;
	char			*p = NULL ;
	int32_t			dp ;
	int32_t			len ;
	
	int16_t			sht ;
	int32_t			i ;
	int64_t			l ;
	float			f ;
	double			d ;
	unsigned char		b ;
	char			*str ;
	int32_t			str_len ;
	
	int			nret = 0 ;
	
	if( IsTypeOf( rt , o , GetArrayObjectInRuntimeObjectsHeap(rt) ) || IsTypeOf( rt , o , GetListObjectInRuntimeObjectsHeap(rt) ) || IsTypeOf( rt , o , GetMapObjectInRuntimeObjectsHeap(rt) ) )
	{
		return ArrayObjectToString( rt , o , s , obj_to_str_style , depth+1 ) ;
	}
	
	if( obj_to_str_style == OBJECTTOSTRING_STYLE_COMPACT )
	{
		CallRuntimeFunction_string_PrepareBuffer( rt , s , 1 );
		CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
		*(p) = '{' ; p++;
		(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
	}
	else if( obj_to_str_style == OBJECTTOSTRING_STYLE_INDENT_TAB )
	{
		CallRuntimeFunction_string_PrepareBuffer( rt , s , depth + 1 + 1 );
		CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
		for( dp = 0 ; dp < depth ; dp++ ) { *(p) = '\t' ; p++; }
		*(p) = '{' ; p++;
		*(p) = '\n' ; p++;
		(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
	}
	
	for( ; ; )
	{
		prop = TravelPropertyInObject( rt , o , prop ) ;
		if( prop == NULL )
			break;
		
		if( prop_name )
		{
			if( obj_to_str_style == OBJECTTOSTRING_STYLE_COMPACT )
			{
				CallRuntimeFunction_string_PrepareBuffer( rt , s , 1 );
				CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
				*(p) = ',' ; p++;
				(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
			}
			else if( obj_to_str_style == OBJECTTOSTRING_STYLE_INDENT_TAB )
			{
				CallRuntimeFunction_string_PrepareBuffer( rt , s , depth + 1 + 1 + 1 );
				CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
				for( dp = 0 ; dp < depth ; dp++ ) { *(p) = '\t' ; p++; }
				*(p) = ' ' ; p++;
				*(p) = ',' ; p++;
				*(p) = '\n' ; p++;
				(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
			}
		}
		
		prop_name = GetObjectName(prop) ;
		prop_name_len = (int32_t)strlen(prop_name) ;
		if( obj_to_str_style == OBJECTTOSTRING_STYLE_COMPACT )
		{
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 1 + prop_name_len + 1 + 1 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			*(p) = '"' ; p++;
			memcpy( p , prop_name , prop_name_len ); p += prop_name_len ;
			*(p) = '"' ; p++;
			*(p) = ':' ; p++;
			(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
		}
		else if( obj_to_str_style == OBJECTTOSTRING_STYLE_INDENT_TAB )
		{
			CallRuntimeFunction_string_PrepareBuffer( rt , s , depth + 1 + prop_name_len + 1 + 1 + 1 + 1 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			for( dp = 0 ; dp < depth ; dp++ ) { *(p) = '\t' ; p++; }
			*(p) = '"' ; p++;
			memcpy( p , prop_name , prop_name_len ); p += prop_name_len ;
			*(p) = '"' ; p++;
			*(p) = ' ' ; p++;
			*(p) = ':' ; p++;
			*(p) = ' ' ; p++;
			(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
		}
		
		if( IsObjectPropertiesEntityNull( prop ) )
		{
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 6 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 6-1 , "null" ) ;
			if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , prop , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_bool_GetBoolValue( rt , prop , & b );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 7 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			if( b )
				len = snprintf( p , 7-1 , "true" ) ;
			else
				len = snprintf( p , 7-1 , "false" ) ;
			if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , prop , GetStringObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_string_GetStringValue( rt , prop , & str , & str_len );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 1 + str_len + 1 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			*(p) = '"' ; p++;
			memcpy( p , str , str_len ); p += str_len ;
			*(p) = '"' ; p++;
			(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
		}
		else if( IsTypeOf( rt , prop , GetShortObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_short_GetShortValue( rt , prop , & sht );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 20 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 20-1 , "%"PRIi16 , sht ) ; if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , prop , GetIntObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_int_GetIntValue( rt , prop , & i );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 40 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 40-1 , "%"PRIi32 , i ) ; if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , prop , GetLongObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_long_GetLongValue( rt , prop , & l );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 80 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 80-1 , "%"PRIi64 , l ) ; if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , prop , GetFloatObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_float_GetFloatValue( rt , prop , & f );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 80 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 80-1 , "%f" , f ) ; if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , prop , GetDoubleObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_double_GetDoubleValue( rt , prop , & d );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 160 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 160-1 , "%lf" , d ) ; if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , prop , GetArrayObjectInRuntimeObjectsHeap(rt) ) || IsTypeOf( rt , prop , GetListObjectInRuntimeObjectsHeap(rt) ) || IsTypeOf( rt , prop , GetMapObjectInRuntimeObjectsHeap(rt) ) )
		{
			nret = ArrayObjectToString( rt , prop , s , obj_to_str_style , depth+1 ) ;
			if( nret )
				return nret;
		}
		else
		{
			nret = ObjectToString( rt , prop , s , obj_to_str_style , depth+1 ) ;
			if( nret )
				return nret;
		}
	}
	
	if( obj_to_str_style == OBJECTTOSTRING_STYLE_COMPACT )
	{
		CallRuntimeFunction_string_PrepareBuffer( rt , s , 1 );
		CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
		*(p) = '}' ; p++;
		(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
	}
	else if( obj_to_str_style == OBJECTTOSTRING_STYLE_INDENT_TAB )
	{
		CallRuntimeFunction_string_PrepareBuffer( rt , s , depth + 1 + 1 );
		CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
		for( dp = 0 ; dp < depth ; dp++ ) { *(p) = '\t' ; p++; }
		*(p) = '}' ; p++;
		*(p) = '\n' ; p++;
		(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
	}
	
	return 0;
}

static int ArrayObjectToString( struct ZlangRuntime *rt , struct ZlangObject *o , struct ZlangObject *s , int32_t obj_to_str_style , int32_t depth )
{
	struct ZlangObject	*iterator_obj = NULL ;
	struct ZlangObject	*element = NULL ;
	struct ZlangObject	*key = NULL ;
	
	/*
	struct ZlangObject	*element = NULL ;
	*/
	char			**buf = NULL ;
	int32_t			*buf_len = NULL ;
	char			*p = NULL ;
	int32_t			dp ;
	int32_t			len ;
	/*
	int32_t			element_count ;
	*/
	int32_t			element_no ;
	
	int16_t			sht ;
	int32_t			i ;
	int64_t			l ;
	float			f ;
	double			d ;
	unsigned char		b ;
	char			*str ;
	int32_t			str_len ;
	
	int			nret = 0 ;
	
	if( obj_to_str_style == OBJECTTOSTRING_STYLE_COMPACT )
	{
		CallRuntimeFunction_string_PrepareBuffer( rt , s , 1 );
		CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
		*(p) = '[' ; p++;
		(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
	}
	else if( obj_to_str_style == OBJECTTOSTRING_STYLE_INDENT_TAB )
	{
		CallRuntimeFunction_string_PrepareBuffer( rt , s , depth + 1 + 1 );
		CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
		for( dp = 0 ; dp < depth ; dp++ ) { *(p) = '\t' ; p++; }
		*(p) = '[' ; p++;
		*(p) = '\n' ; p++;
		(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
	}
	
	iterator_obj = CloneIteratorObjectInTmpStack( rt , NULL ) ;
	if( iterator_obj == NULL )
		return GetRuntimeErrorNo(rt);
	
	nret = CallRuntimeFunction_iterator_TravelFirst( rt , iterator_obj , o ) ;
	if( nret )
		return nret;
	
	for( element_no = 1 ; ! CallRuntimeFunction_iterator_IsTravelOver( rt , iterator_obj ) ; CallRuntimeFunction_iterator_TravelNext( rt , iterator_obj) , element_no++ )
	{
		nret = CallRuntimeFunction_iterator_GetElement( rt , iterator_obj , & element ) ;
		if( nret )
			break;
		
		if( IsTypeOf( rt , o , GetMapObjectInRuntimeObjectsHeap(rt) ) )
		{
			key = element ;
			element = NULL ;
			CallRuntimeFunction_map_Get( rt , o , key , & element );
		}
		
		if( element_no > 1 )
		{
			if( obj_to_str_style == OBJECTTOSTRING_STYLE_COMPACT )
			{
				CallRuntimeFunction_string_PrepareBuffer( rt , s , 1 );
				CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
				*(p) = ',' ; p++;
				(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
			}
			else if( obj_to_str_style == OBJECTTOSTRING_STYLE_INDENT_TAB )
			{
				CallRuntimeFunction_string_PrepareBuffer( rt , s , depth + 1 + 1 + 1 );
				CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
				for( dp = 0 ; dp < depth ; dp++ ) { *(p) = '\t' ; p++; }
				*(p) = ' ' ; p++;
				*(p) = ',' ; p++;
				*(p) = '\n' ; p++;
				(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
			}
		}
		
		if( IsTypeOf( rt , o , GetMapObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_string_GetStringValue( rt , key , & str , & str_len );
			
			if( obj_to_str_style == OBJECTTOSTRING_STYLE_COMPACT )
			{
				CallRuntimeFunction_string_PrepareBuffer( rt , s , 1 + str_len + 1 + 1 );
				CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
				*(p) = '"' ; p++;
				memcpy( p , str , str_len ); p += str_len ;
				*(p) = '"' ; p++;
				*(p) = ':' ; p++;
				(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
			}
			else if( obj_to_str_style == OBJECTTOSTRING_STYLE_INDENT_TAB )
			{
				CallRuntimeFunction_string_PrepareBuffer( rt , s , depth + 1 + str_len + 1 + 1 + 1 + 1 );
				CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
				for( dp = 0 ; dp < depth ; dp++ ) { *(p) = '\t' ; p++; }
				*(p) = '"' ; p++;
				memcpy( p , str , str_len ); p += str_len ;
				*(p) = '"' ; p++;
				*(p) = ' ' ; p++;
				*(p) = ':' ; p++;
				*(p) = ' ' ; p++;
				(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
			}
		}
		
		if( IsObjectPropertiesEntityNull( element ) )
		{
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 6 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 6-1 , "null" ) ;
			if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , element , GetBoolObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_bool_GetBoolValue( rt , element , & b );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 7 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			if( b )
				len = snprintf( p , 7-1 , "true" ) ;
			else
				len = snprintf( p , 7-1 , "false" ) ;
			if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , element , GetStringObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_string_GetStringValue( rt , element , & str , & str_len );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 1 + str_len + 1 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			*(p) = '"' ; p++;
			memcpy( p , str , str_len ); p += str_len ;
			*(p) = '"' ; p++;
			(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
		}
		else if( IsTypeOf( rt , element , GetShortObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_short_GetShortValue( rt , element , & sht );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 20 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 20-1 , "%"PRIi16 , sht ) ; if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , element , GetIntObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_int_GetIntValue( rt , element , & i );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 40 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 40-1 , "%"PRIi32 , i ) ; if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , element , GetLongObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_long_GetLongValue( rt , element , & l );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 80 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 80-1 , "%"PRIi64 , l ) ; if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , element , GetFloatObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_float_GetFloatValue( rt , element , & f );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 80 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 80-1 , "%f" , f ) ; if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , element , GetDoubleObjectInRuntimeObjectsHeap(rt) ) )
		{
			CallRuntimeFunction_double_GetDoubleValue( rt , element , & d );
			
			CallRuntimeFunction_string_PrepareBuffer( rt , s , 160 );
			CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
			len = snprintf( p , 160-1 , "%lf" , d ) ; if( len > 0 ) (*buf_len) += len ;
		}
		else if( IsTypeOf( rt , element , GetArrayObjectInRuntimeObjectsHeap(rt) ) || IsTypeOf( rt , element , GetListObjectInRuntimeObjectsHeap(rt) ) || IsTypeOf( rt , element , GetMapObjectInRuntimeObjectsHeap(rt) ) )
		{
			nret = ArrayObjectToString( rt , element , s , obj_to_str_style , depth+1 ) ;
			if( nret )
				return nret;
		}
		else
		{
			nret = ObjectToString( rt , element , s , obj_to_str_style , depth+1 ) ;
			if( nret )
				return nret;
		}
	}
	
	if( obj_to_str_style == OBJECTTOSTRING_STYLE_COMPACT )
	{
		CallRuntimeFunction_string_PrepareBuffer( rt , s , 1 );
		CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
		*(p) = ']' ; p++;
		(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
	}
	else if( obj_to_str_style == OBJECTTOSTRING_STYLE_INDENT_TAB )
	{
		CallRuntimeFunction_string_PrepareBuffer( rt , s , depth + 1 + 1 );
		CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
		for( dp = 0 ; dp < depth ; dp++ ) { *(p) = '\t' ; p++; }
		*(p) = ']' ; p++;
		*(p) = '\n' ; p++;
		(*buf_len) += (int32_t)( p - (*(buf)+*(buf_len)) ) ;
	}
	
	CallRuntimeFunction_string_GetDirectPropertiesPtr( rt , s , & buf , NULL , & buf_len ); p = *(buf) + *(buf_len) ;
	*(p) = '\0' ;
	
	return 0;
}

ZlangDirectFunction_json_ObjectToString json_ObjectToString;
int json_ObjectToString( struct ZlangRuntime *rt , struct ZlangObject *obj , struct ZlangObject *o , struct ZlangObject *s , int32_t obj_to_str_style )
{
	return ObjectToString( rt , o , s , obj_to_str_style , 0 );
}

ZlangInvokeFunction ZlangInvokeFunction_json_ObjectToString_object;
int ZlangInvokeFunction_json_ObjectToString_object( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangObject		*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int				nret = 0 ;
	
	nret = json_ObjectToString( rt , obj , in1 , out1 , 0 ) ;
	if( nret )
	{
		nret = UnreferObject( rt , out1 ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InitObject failed[%d]" , nret )
			return nret;
		}
		
		return ThrowErrorException( rt , EXCEPTION_CODE_GENERAL , EXCEPTION_MESSAGE_OBJECT_TO_STRING_FAILED );
	}
	
	return 0;
}

ZlangInvokeFunction ZlangInvokeFunction_json_ObjectToString_object_int;
int ZlangInvokeFunction_json_ObjectToString_object_int( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangObject		*in1 = GetInputParameterInLocalObjectStack(rt,1) ;
	struct ZlangObject		*in2 = GetInputParameterInLocalObjectStack(rt,2) ;
	struct ZlangObject		*out1 = GetOutputParameterInLocalObjectStack(rt,1) ;
	int32_t				obj_to_str_style ;
	int				nret = 0 ;
	
	CallRuntimeFunction_int_GetIntValue( rt , in2 , & obj_to_str_style );
	
	nret = json_ObjectToString( rt , obj , in1 , out1 , obj_to_str_style ) ;
	if( nret )
	{
		nret = UnreferObject( rt , out1 ) ;
		if( nret )
		{
			TEST_RUNTIME_DEBUG_THEN_PRINT( rt , "InitObject failed[%d]" , nret )
			return nret;
		}
		
		return ThrowErrorException( rt , EXCEPTION_CODE_GENERAL , EXCEPTION_MESSAGE_OBJECT_TO_STRING_FAILED );
	}
	
	return 0;
}

ZlangCreateDirectPropertyFunction ZlangCreateDirectProperty_json;
void *ZlangCreateDirectProperty_json( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_json	*json_prop = NULL ;
	
	json_prop = (struct ZlangDirectProperty_json *)ZLMALLOC( sizeof(struct ZlangDirectProperty_json) ) ;
	if( json_prop == NULL )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_ALLOC , "alloc memory for entity" )
		return NULL;
	}
	memset( json_prop , 0x00 , sizeof(struct ZlangDirectProperty_json) );
	
	return json_prop;
}

ZlangDestroyDirectPropertyFunction ZlangDestroyDirectProperty_json;
void ZlangDestroyDirectProperty_json( struct ZlangRuntime *rt , struct ZlangObject *obj )
{
	struct ZlangDirectProperty_json	*json_direct_prop = GetObjectDirectProperty(obj) ;
	
	ZLFREE( json_direct_prop );
	
	return;
}

ZlangSummarizeDirectPropertySizeFunction ZlangSummarizeDirectPropertySize_json;
void ZlangSummarizeDirectPropertySize_json( struct ZlangRuntime *rt , struct ZlangObject *obj , size_t *summarized_obj_size , size_t *summarized_direct_prop_size )
{
	SUMMARIZE_SIZE( summarized_direct_prop_size , sizeof(struct ZlangDirectProperty_json) )
	return;
}

static struct ZlangDirectFunctions direct_funcs_json =
	{
		ZLANG_OBJECT_json , /* char *tpye_name */
		
		ZlangCreateDirectProperty_json , /* ZlangCreateDirectPropertyFunction *create_entity_func */
		ZlangDestroyDirectProperty_json , /* ZlangDestroyDirectPropertyFunction *destroy_entity_func */
		
		NULL , /* ZlangFromCharPtrFunction *from_char_ptr_func */
		NULL , /* ZlangToStringFunction *to_string_func */
		NULL , /* ZlangFromDataPtrFunction *from_data_ptr_func */
		NULL , /* ZlangGetDataPtrFunction *get_data_ptr_func */
		
		NULL , /* ZlangOperatorFunction *oper_PLUS_func */
		NULL , /* ZlangOperatorFunction *oper_MINUS_func */
		NULL , /* ZlangOperatorFunction *oper_MUL_func */
		NULL , /* ZlangOperatorFunction *oper_DIV_func */
		NULL , /* ZlangOperatorFunction *oper_MOD_func */
		
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_NEGATIVE_func */
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_NOT_func */
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_BIT_REVERSE_func */
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_PLUS_PLUS_func */
		NULL , /* ZlangUnaryOperatorFunction *unaryoper_MINUS_MINUS_func */
		
		NULL , /* ZlangCompareFunction *comp_EGUAL_func */
		NULL , /* ZlangCompareFunction *comp_NOTEGUAL_func */
		NULL , /* ZlangCompareFunction *comp_LT_func */
		NULL , /* ZlangCompareFunction *comp_LE_func */
		NULL , /* ZlangCompareFunction *comp_GT_func */
		NULL , /* ZlangCompareFunction *comp_GE_func */
		
		NULL , /* ZlangLogicFunction *logic_AND_func */
		NULL , /* ZlangLogicFunction *logic_OR_func */
		
		NULL , /* ZlangLogicFunction *bit_AND_func */
		NULL , /* ZlangLogicFunction *bit_XOR_func */
		NULL , /* ZlangLogicFunction *bit_OR_func */
		NULL , /* ZlangLogicFunction *bit_MOVELEFT_func */
		NULL , /* ZlangLogicFunction *bit_MOVERIGHT_func */
		
		ZlangSummarizeDirectPropertySize_json , /* ZlangSummarizeDirectPropertySizeFunction *summarize_direct_prop_size_func */
	} ;

ZlangImportObjectFunction ZlangImportObject_json;
struct ZlangObject *ZlangImportObject_json( struct ZlangRuntime *rt )
{
	struct ZlangObject	*obj = NULL ;
	struct ZlangObject	*prop = NULL ;
	struct ZlangFunction	*func = NULL ;
	int			nret = 0 ;
	
	nret = ImportObject( rt , & obj , ZLANG_OBJECT_json , & direct_funcs_json , sizeof(struct ZlangDirectFunctions) , NULL ) ;
	if( nret )
	{
		SET_RUNTIME_ERROR( rt , RUNTIME_ERROR , ZLANG_ERROR_LINK_FUNC_TO_ENTITY , "import object to global objects heap" )
		return NULL;
	}
	
	prop = AddPropertyInObject( rt , obj , GetIntObjectInRuntimeObjectsHeap(rt) , "OBJECTTOSTRING_STYLE_COMPACT") ;
	if( prop == NULL )
		return NULL;
	CallRuntimeFunction_int_SetIntValue( rt , prop , OBJECTTOSTRING_STYLE_COMPACT );
	SetConstantObject( prop );
	
	prop = AddPropertyInObject( rt , obj , GetIntObjectInRuntimeObjectsHeap(rt) , "OBJECTTOSTRING_STYLE_INDENT_TAB") ;
	if( prop == NULL )
		return NULL;
	CallRuntimeFunction_int_SetIntValue( rt , prop , OBJECTTOSTRING_STYLE_INDENT_TAB );
	SetConstantObject( prop );
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_json_StringToObject_string , ZLANG_OBJECT_object , "StringToObject" , ZLANG_OBJECT_string,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_json_StringToEntityObject_string_object , ZLANG_OBJECT_bool , "StringToEntityObject" , ZLANG_OBJECT_string,NULL , ZLANG_OBJECT_object,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_json_ObjectToString_object , ZLANG_OBJECT_string , "ObjectToString" , ZLANG_OBJECT_object,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	func = AddFunctionAndParametersInObject( rt , obj , ZlangInvokeFunction_json_ObjectToString_object_int , ZLANG_OBJECT_string , "ObjectToString" , ZLANG_OBJECT_object,NULL , ZLANG_OBJECT_int,NULL , NULL ) ;
	if( func == NULL )
		return NULL;
	
	SetRuntimeFunction_json_StringToObject( rt , json_StringToObject );
	SetRuntimeFunction_json_ObjectToString( rt , json_ObjectToString );
	
	return obj ;
}

